package com.ssy.lingxi.platform.manage.serviceimpl.content;

import cn.hutool.core.collection.CollectionUtil;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.platform.manage.constant.CommonBooleanEnum;
import com.ssy.lingxi.platform.manage.entity.content.ContentCategory;
import com.ssy.lingxi.platform.manage.entity.content.ContentInformation;
import com.ssy.lingxi.platform.manage.model.request.common.CommonIdRequest;
import com.ssy.lingxi.platform.manage.model.request.content.ContentCategoryRequest;
import com.ssy.lingxi.platform.manage.model.response.ContentCategoryResponse;
import com.ssy.lingxi.platform.manage.repository.ContentCategoryRepository;
import com.ssy.lingxi.platform.manage.repository.ContentInformationRepository;
import com.ssy.lingxi.platform.manage.service.content.IContentCategoryService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 分类管理 - 业务实现层
 * @author fhj
 * @version 2.0.0
 * @date 2021/04/25
 */
@Service
public class ContentCategoryServiceImpl implements IContentCategoryService {

    @Resource
    private ContentCategoryRepository contentCategoryRepository;
    @Resource
    private ContentInformationRepository contentInformationRepository;

    /**
     *所有
     * @return 操作结果
     */
    @Override
    public Wrapper<List<ContentCategoryResponse>> all() {
        //获取所有分类
        List<ContentCategory> all = contentCategoryRepository.findAll();

        //先拿到所有一级分类再根据父级ID匹配递归封装子级分类
        List<ContentCategoryResponse> list = all.stream().filter(a -> a.getParentId().equals(0L)
                ).map(b -> {
                    ContentCategoryResponse response = new ContentCategoryResponse();
                    BeanUtils.copyProperties(b, response);
                    response.setList(getChildren(b, all));
                    return response;
                }).sorted(Comparator.comparingLong(ContentCategoryResponse::getId)).collect(Collectors.toList());

        return Wrapper.success(list);
    }

    /**
     * 详情
     * @param request 请求体
     * @return 操作结果
     */
    @Override
    public Wrapper<ContentCategory> get(CommonIdRequest request) {
        return Wrapper.success(contentCategoryRepository.findById(request.getId()).orElse(null));
    }

    /**
     * 新增
     * @param request 参数实体
     * @param user 当前登录用户
     * @return 操作结果
     */
    @Override
    @Transactional
    public Wrapper<Void> add(ContentCategoryRequest request, UserLoginCacheDTO user) {
        //校验
        if(request.getLevel() == 3 && request.getStatus() == null) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_CATEGORY_CANNOT_BE_EMPTY);
        }
        if(request.getLevel() != 3 && request.getStatus() != null && request.getStatus().equals(CommonBooleanEnum.YES.getCode())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_SELECTED_AS_RECOMMENDED_CATEGORY);
        }

        //当新增分类为第三级时，获取到冗余字段第一级分类
        Long firstId = null;
        if(request.getLevel().equals(3)) {
            ContentCategory contentCategory = contentCategoryRepository.findById(request.getParentId()).orElse(null);
            if(contentCategory != null) {
                contentCategory = contentCategoryRepository.findById(contentCategory.getParentId()).orElse(null);
                if(contentCategory != null) {
                    firstId = contentCategory.getId();

                    //如果设置3级分类为推荐分类时, 需要校验。先获取三级分类（推荐）再进行校验
                    if(request.getStatus().equals(CommonBooleanEnum.YES.getCode())) {
                        List<ContentCategory> thirdlyList = contentCategoryRepository.findAllByStatusAndLevel(CommonBooleanEnum.YES.getCode(), 3);
                        if(CollectionUtil.isNotEmpty(thirdlyList)) {
                            Long finalFirstId = firstId;
                            if(thirdlyList.stream().filter(a -> a.getFirstId().equals(finalFirstId)).count() >= 2) {
                                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_ONLY_ALLOW_SETTING_TWO_RECOMMENDED_CATEGORY);
                            }
                            if(thirdlyList.stream().filter(a -> !a.getFirstId().equals(finalFirstId)).collect(Collectors.groupingBy(ContentCategory::getFirstId)).size() >= 7) {
                                return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_SET_RECOMMENDED_CATEGORIES);
                            }
                        }
                    }
                }
            }
        }

        ContentCategory contentCategory = new ContentCategory();
        BeanUtils.copyProperties(request, contentCategory);
        contentCategory.setFirstId(firstId);
        contentCategoryRepository.saveAndFlush(contentCategory);
        return Wrapper.success();
    }

    /**
     * 修改
     * @param request 请求实体
     * @param user 当前登录用户
     * @return 操作结果
     */
    @Override
    @Transactional
    public Wrapper<Void> update(ContentCategoryRequest request, UserLoginCacheDTO user) {
        //校验
        if(request.getLevel() == 3 && request.getStatus() == null) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_RECOMMENDED_CATEGORY_CANNOT_BE_EMPTY);
        }

        //根据ID获取分类
        ContentCategory contentCategory = contentCategoryRepository.findById(request.getId()).orElse(null);
        if(contentCategory == null) {
            return Wrapper.fail(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }

        //如果修改3级分类为推荐分类并且该分类在修改之前为非推荐分类时, 需要校验。先获取三级分类（推荐）再进行校验
        if(request.getLevel().equals(3) && request.getStatus().equals(CommonBooleanEnum.YES.getCode()) && contentCategory.getStatus().equals(CommonBooleanEnum.NO.getCode())) {
            List<ContentCategory> thirdlyList = contentCategoryRepository.findAllByStatusAndLevel(CommonBooleanEnum.YES.getCode(), 3);
            if(CollectionUtil.isNotEmpty(thirdlyList)) {
                if(thirdlyList.stream().filter(a -> a.getFirstId().equals(contentCategory.getFirstId())).count() >= 2) {
                    return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_ONLY_ALLOW_SETTING_TWO_RECOMMENDED_CATEGORY);
                }
                if(thirdlyList.stream().filter(a -> !a.getFirstId().equals(contentCategory.getFirstId())).collect(Collectors.groupingBy(ContentCategory::getFirstId)).size() >= 7) {
                    return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_SET_RECOMMENDED_CATEGORIES);
                }
            }
        }

        //修改分类
        BeanUtils.copyProperties(request, contentCategory);
        contentCategoryRepository.saveAndFlush(contentCategory);

        //获取关联分类ID的资讯，根据分类等级来批量更新资讯的对应等级分类名称
        List<ContentInformation> list = contentInformationRepository.findAllByFirstCategoryIdOrSecondCategoryIdOrThirdlyCategoryId(
                request.getId(), request.getId(), request.getId()
        );
        if(CollectionUtil.isNotEmpty(list)) {
            if(request.getLevel().equals(1)) {
                list = list.stream().peek(a -> a.setFirstCategoryName(request.getName())).collect(Collectors.toList());
            }else if(request.getLevel().equals(2)) {
                list = list.stream().peek(a -> a.setSecondCategoryName(request.getName())).collect(Collectors.toList());
            }else {
                list = list.stream().peek(a -> a.setThirdlyCategoryName(request.getName())).collect(Collectors.toList());
            }
            contentInformationRepository.saveAll(list);
        }

        return Wrapper.success();
    }

    /**
     * 删除
     * @param request 请求实体
     * @param user 当前登录用户
     * @return 操作结果
     */
    @Override
    @Transactional
    public Wrapper<Void> delete(CommonIdRequest request, UserLoginCacheDTO user) {
        if(contentCategoryRepository.existsByParentId(request.getId())) {
            return Wrapper.fail(ResponseCode.PLATFORM_MANAGE_PLEASE_DELETE_SUB_CATEGORIES_FIRST);
        }
        if(contentInformationRepository.existsAllByFirstCategoryIdOrSecondCategoryIdOrThirdlyCategoryId(request.getId(), request.getId(), request.getId())) {
            return Wrapper.fail(ResponseCode.MAN_DATA_RELATION_INFORMATION);
        }
        contentCategoryRepository.deleteById(request.getId());
        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "推荐分类")
    public Wrapper<List<ContentCategoryResponse>> recommend() {
        //获取一级分类
        List<ContentCategory> firstList = contentCategoryRepository.findAllByLevel(1, Sort.by("id"));

        //获取三级分类（推荐）
        List<ContentCategory> thirdlyList = contentCategoryRepository.findAllByStatusAndLevel(CommonBooleanEnum.YES.getCode(), 3);

        //将推荐的第三级分类根据第一级分类ID进行分组筛选
        Map<Long, List<ContentCategoryResponse>> map = thirdlyList.stream().map(a -> {
                    ContentCategoryResponse response = new ContentCategoryResponse();
                    BeanUtils.copyProperties(a, response);
                    return response;
                }).sorted(Comparator.comparingLong(ContentCategoryResponse::getId)).collect(Collectors.groupingBy(ContentCategoryResponse::getFirstId));

        //将一级分类按map内的key进行筛选并完成最后封装
        List<ContentCategoryResponse> list = firstList.stream().filter(a -> map.containsKey(a.getId())).map(a -> {
            ContentCategoryResponse response = new ContentCategoryResponse();
            BeanUtils.copyProperties(a, response);
            response.setList(map.get(a.getId()));
            return response;
        }).sorted(Comparator.comparingLong(ContentCategoryResponse::getId)).collect(Collectors.toList());


        return Wrapper.success(list);
    }

    /**
     * 分类递归
     * */
    private List<ContentCategoryResponse> getChildren(ContentCategory root, List<ContentCategory> all) {
        return all.stream().filter(a -> a.getParentId().equals(root.getId()))
                .map(b -> {
                    ContentCategoryResponse response = new ContentCategoryResponse();
                    BeanUtils.copyProperties(b, response);
                    response.setList(getChildren(b, all));
                    return response;
                }).sorted(Comparator.comparingLong(ContentCategoryResponse::getId)).collect(Collectors.toList());
    }
}
